package com.k12.admim.utils;

import org.apache.commons.lang3.StringUtils;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.SecureRandom;
import java.security.Security;
import java.util.Arrays;
import java.util.Base64;

@Component
public class AesUtils {
    
    // AES加密算法
    private static final String ALGORITHM = "AES";
    // AES加密模式
    private static final String TRANSFORMATION = "AES/CBC/PKCS5Padding";

    // 从配置文件中读取密钥，实际生产环境应从KMS获取
    //@Value("${aes.secret.key}")
    private static String secretKey ="weweweweweqw2356";
    
    // 初始化向量长度
    private static final int IV_LENGTH = 16;
    
    static {
        // 添加BouncyCastleProvider支持
        Security.addProvider(new BouncyCastleProvider());
    }
    
    /**
     * 加密方法  相同的明文每次调用会生成不同的密文
     * @param plainText 明文
     * @return Base64编码的密文(包含IV)
     */
    public static String encrypt(String plainText) throws Exception {
        if (StringUtils.isBlank(plainText)) {
            return plainText;
        }
        
        // 生成随机初始化向量
        byte[] iv = new byte[IV_LENGTH];
        SecureRandom random = new SecureRandom();
        random.nextBytes(iv);
        IvParameterSpec ivSpec = new IvParameterSpec(iv);
        
        // 创建密钥
        SecretKeySpec keySpec = new SecretKeySpec(secretKey.getBytes(StandardCharsets.UTF_8), ALGORITHM);
        
        // 初始化加密器
        Cipher cipher = Cipher.getInstance(TRANSFORMATION);
        cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec);
        
        // 执行加密
        byte[] encrypted = cipher.doFinal(plainText.getBytes(StandardCharsets.UTF_8));
        
        // 组合IV和加密数据
        byte[] combined = new byte[iv.length + encrypted.length];
        System.arraycopy(iv, 0, combined, 0, iv.length);
        System.arraycopy(encrypted, 0, combined, iv.length, encrypted.length);
        
        // 返回Base64编码的字符串
        return Base64.getEncoder().encodeToString(combined);
    }
    
    /**
     * 解密方法
     * @param encryptedText Base64编码的密文(包含IV)
     * @return 解密后的明文
     */
    public static  String decrypt(String encryptedText) throws Exception {
        if (StringUtils.isBlank(encryptedText)) {
            return encryptedText;
        }
        
        // 解码Base64
        byte[] combined = Base64.getDecoder().decode(encryptedText);
        
        // 提取IV
        byte[] iv = new byte[IV_LENGTH];
        System.arraycopy(combined, 0, iv, 0, iv.length);
        IvParameterSpec ivSpec = new IvParameterSpec(iv);
        
        // 提取加密数据
        byte[] encrypted = new byte[combined.length - IV_LENGTH];
        System.arraycopy(combined, IV_LENGTH, encrypted, 0, encrypted.length);
        
        // 创建密钥
        SecretKeySpec keySpec = new SecretKeySpec(secretKey.getBytes(StandardCharsets.UTF_8), ALGORITHM);
        
        // 初始化解密器
        Cipher cipher = Cipher.getInstance(TRANSFORMATION);
        cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);
        
        // 执行解密
        byte[] decrypted = cipher.doFinal(encrypted);
        
        return new String(decrypted, StandardCharsets.UTF_8);
    }
    
    /**
     * 生成AES密钥(256位)
     */
    public static String generateAesKey() throws Exception {
        KeyGenerator keyGen = KeyGenerator.getInstance(ALGORITHM);
        keyGen.init(256); // 使用256位密钥
        SecretKey secretKey = keyGen.generateKey();
        return Base64.getEncoder().encodeToString(secretKey.getEncoded());
    }

    /**
     * 确定性加密(相同明文始终得到相同密文)
     * 适用于需要查询的字段
     */
    public static String deterministicEncrypt(String plainText) throws Exception {
        if (StringUtils.isBlank(plainText)) {
            return plainText;
        }

        // 使用固定IV(从密钥派生)
        byte[] iv = Arrays.copyOfRange(
                secretKey.getBytes(StandardCharsets.UTF_8), 0, IV_LENGTH);
        IvParameterSpec ivSpec = new IvParameterSpec(iv);

        SecretKeySpec keySpec = new SecretKeySpec(secretKey.getBytes(StandardCharsets.UTF_8), ALGORITHM);

        Cipher cipher = Cipher.getInstance(TRANSFORMATION);
        cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec);

        byte[] encrypted = cipher.doFinal(plainText.getBytes(StandardCharsets.UTF_8));
        return Base64.getEncoder().encodeToString(encrypted);
    }

    /**
     * 生成查询用的加密值
     */
    public static  String getSearchableValue(String plainText) throws Exception {
        return deterministicEncrypt(plainText);
    }

    /**
     * 确定性解密(配合deterministicEncrypt使用)
     */
    public static String deterministicDecrypt(String encryptedText) throws Exception {
        if (StringUtils.isBlank(encryptedText)) {
            return encryptedText;
        }

        // 使用与加密时相同的固定IV
        byte[] iv = Arrays.copyOfRange(
                secretKey.getBytes(StandardCharsets.UTF_8), 0, IV_LENGTH);
        IvParameterSpec ivSpec = new IvParameterSpec(iv);

        // 创建密钥
        SecretKeySpec keySpec = new SecretKeySpec(secretKey.getBytes(StandardCharsets.UTF_8), ALGORITHM);

        // 初始化解密器
        Cipher cipher = Cipher.getInstance(TRANSFORMATION);
        cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);

        // 执行解密
        byte[] decrypted = cipher.doFinal(Base64.getDecoder().decode(encryptedText));

        return new String(decrypted, StandardCharsets.UTF_8);
    }
}